﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using IntoNails.DataAccess;
using IntoNails.Infrastructure;
using IntoNails.Infrastructure.DataAccess;
using IntoNails.Infrastructure.ViewModels;
using IntoNails.Models;
using IntoNails.Modules.CategoryManagement.EventAggregators;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;

namespace IntoNails.Modules.CategoryManagement.ViewModels
{
    [Export(typeof(ICategoryTreeViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class CategoryTreeViewModel : WorkspaceViewModel, ICategoryTreeViewModel
    {
        #region Fields

        private readonly IEventAggregator _eventAggregator;
        private readonly CategoryRepository _categoryRepository;

        private ObservableCollection<TreeNodeViewModel> _categoryTreeNodeCollection;
        private TreeNodeViewModel _selectedCategoryNode;

        #endregion

        #region Constructors

        [ImportingConstructor]
        public CategoryTreeViewModel(IEventAggregator eventAggregator)
        {
            this._eventAggregator = eventAggregator;
            this._eventAggregator.GetEvent<NewCategoryCreatedEventAggregator>().Subscribe(this.OnNewCategoryCreated, ThreadOption.UIThread);

            Category rootCategory = Category.RootCategory;
            this.RootCategoryNode = new TreeNodeViewModel(rootCategory.DisplayName, null, rootCategory, rootCategory);

            this.SelectedCategoryNode = this.RootCategoryNode;
            
            this._categoryRepository = new CategoryRepository(GlobalInformation.StartUpPath + @"\Data\Category.dat");
            this._categoryRepository.Load();
            this._categoryRepository.Added += CategoryRepositoryOnAdded;
            this._categoryRepository.Updated += CategoryRepositoryOnUpdated;
            this._categoryRepository.Removed += CategoryRepositoryOnRemoved;
            this._categoryRepository.Load();

            this.PopulateCategoryTree();
        }

        #endregion

        #region Properties

        public ObservableCollection<TreeNodeViewModel> CategoryTreeNodeCollection
        {
            get { return this._categoryTreeNodeCollection; }
            set
            {
                this._categoryTreeNodeCollection = value;
                base.RaisePropertyChanged(() => CategoryTreeNodeCollection);
            }
        }

        public TreeNodeViewModel SelectedCategoryNode
        {
            get { return this._selectedCategoryNode; }
            set
            {
                this._selectedCategoryNode = value;
                base.RaisePropertyChanged(() => SelectedCategoryNode);
            }
        }

        public TreeNodeViewModel RootCategoryNode { get; private set; }

        #endregion

        #region Commands

        public DelegateCommand SaveCommand { get; private set; }
        public DelegateCommand CancelCommand { get; private set; }

        #endregion

        public override void Init()
        {
            base.Init();

            this.CategoryTreeNodeCollection = new ObservableCollection<TreeNodeViewModel>();

            TreeNodeViewModel rootCategoryNode = new TreeNodeViewModel("Services")
                                                     {
                                                         IsExpanded = true,
                                                         IsReadonly = true
                                                     };

            rootCategoryNode.Notify += CategoryNodeOnNotify;

            this.CategoryTreeNodeCollection.Add(rootCategoryNode);
        }

        private void CategoryNodeOnNotify(TreeNodeViewModel currentNode)
        {
            switch (currentNode.Status)
            {
                case NodeStatus.Added:
                    break;
                case NodeStatus.Edited:
                    break;
                case NodeStatus.Deleted:
                    break;
            }
        }

        protected override void RegisterCommands()
        {
            this.SaveCommand = new DelegateCommand(this.ExecuteSaveCommand, this.CanExecuteSaveCommand);
            this.CancelCommand = new DelegateCommand(this.ExecuteCancelCommand, this.CanExecuteCancelCommand);
        }

        #region Command Actions

        private void ExecuteSaveCommand()
        {
            
        }

        private void ExecuteCancelCommand()
        {
            
        }

        #endregion

        #region Command Predicates

        private bool CanExecuteSaveCommand()
        {
            return false;
        }

        private bool CanExecuteCancelCommand()
        {
            return false;
        }

        #endregion

        #region Event Aggregator Subcribers

        /// <summary>
        /// 
        /// </summary>
        /// <param name="category"></param>
        private void OnNewCategoryCreated(Category category)
        {
            category.Parent = this.SelectedCategoryNode.AssociatedObject as Category;
            
            this._categoryRepository.Add(category);

            TreeNodeViewModel newCategoryNode = new TreeNodeViewModel(category.DisplayName,
                                                                      this.SelectedCategoryNode,
                                                                      category, category);

            this.SelectedCategoryNode.Children.Add(newCategoryNode);
        }

        #endregion

        #region Event Handlers

        private void CategoryRepositoryOnRemoved(object sender, Infrastructure.DataAccess.DataEventArgs<Category> dataEventArgs)
        {
        }

        private void CategoryRepositoryOnUpdated(object sender, DataUpdatedEventArgs<Category> dataUpdatedEventArgs)
        {
        }

        private void CategoryRepositoryOnAdded(object sender, Infrastructure.DataAccess.DataEventArgs<Category> dataEventArgs)
        {
        }

        #endregion

        #region Private Helpers

        private void PopulateCategoryTree()
        {
            this.CategoryTreeNodeCollection = new ObservableCollection<TreeNodeViewModel> {this.RootCategoryNode};

            ////foreach (var category in this._categoryRepository.GetRawItemList())
            ////{
            ////    TreeNodeViewModel categoryNode = new 
            ////}

        }

        #endregion
    }
}
